<?php
/**
 * @desc bootstrap class file
 * @author nana
 * @date 2011
 * @usage:
 * NICED_Bootstrap::getInstance()->init();
 *
 */
class NICED_Bootstrap
{
	private static $inited = false;
	private static $instance = null;
	private static $autoloadDirs = array();
	private static $secondDomains = array("www", "js", "css", "images");


	public function __construct()
	{
		//self::init();
        set_exception_handler(array($this, "exceptionHandler"));
        register_shutdown_function(array(__CLASS__, "shutdown"));
	}

    public static function getInstance()
	{	
		if (!self::$instance)
		{
			$classname = __CLASS__;
			self::$instance = new $classname();
		}

		return self::$instance;
	}


	/**
	 * @desc init
	 * @return void
	 */
	public static function init() 
	{
		if (self::$inited) 
		{
			return true;
		}

		//default load some files,include class and function lib
		$files = self::getLoadFiles();
		foreach ($files as $s)
		{
			require_once $s;
		}

		
		//init autoload dirs
		self::initAutoLoadDir();

		//init config,load from config dir to array or memcache or other type
        $config = NICED_Config::getInstance();
        $config->init();

        NICED_TIME_START("application", NICED_START_MS);
        NICED_TIME_STOP("application", "finish_init_config");
		self::initBoardConfig();

        //log param
        $log_level = SC::get("board_config.niced_log_level");
        NICED_LOG($log_level, $_GET, NICED." \$_GET");
        //NICED_LOG($log_level, $_POST, NICED." \$_POST");
        NICED_LOG($log_level, NICED." REQUEST URI ".$_SERVER["REQUEST_URI"]);
        NICED_LOG($log_level, NICED." QUERY_STRING ".$_SERVER["QUERY_STRING"]);
        $referer = isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : NULL;
        NICED_LOG($log_level, NICED." HTTP_REFERER ".$referer);
        NICED_LOG($log_level, NICED." REQUEST_TIME ".$_SERVER["REQUEST_TIME"]);

		self::$inited = true;
	}

	protected static function getLoadFiles()
	{
		$files = array(
			DIR_CORE.'container.php',
			DIR_CORE.'config.php',
			DIR_CORE.'mvc'.DS.'controller.php',
			DIR_CORE.'mvc'.DS.'model.php',
			DIR_CORE.'mvc'.DS.'view.php',
			DIR_CORE.'mvc'.DS.'action.php',
			DIR_CORE.'request.php',
			DIR_CORE.'exception.php',
			DIR_CORE.'url.php',
			DIR_CORE.'functions.php',
		);

		return $files;
	}

	protected static function initAutoLoadDir()
	{
		self::$autoloadDirs = array(
			0 => DIR_CORE,
			1 => DIR_LIBRARY,
			2 => DIR_CORE.'db'.DS,
			3 => DIR_CLASSES,
			4 => DIR_HELPER,
			5 => DIR_UTIL,
		);	

		return true;
	}


	/**
	 * @desc for spl auto load
	 * @return void
	 */
	public static function autoloadClass($class_name) 
    {
		//all case for special files, maybe one file has some class
		switch ($class_name)
        {
            //for class name is not equal to filename
			case 'NICED_Transaction' :
			{	
			}
			case 'NICED_MysqlTransaction' :
			{
				return include(DIR_CORE.'db'.DS.'transaction.php');
				break;
			}
			case 'NICED_RealTimeDao' :
			{
				return include(DIR_CORE.'db'.DS.'dao.php');
				break;
			}
			case 'TM' :
			{
				return include(DIR_CORE.'templatemanager.php');
				break;
			}
			case 'FS' :
			{
				return include(DIR_LIBRARY.'formatshow.php');
				break;
			}
            //for normal class,file name is equal to classname strip niced_
	    	default :
		    {
                $class_name = strtolower($class_name);
				$class_name = str_replace('niced_', '', $class_name);

                //$db_files = array(
                //    "database.php", 
                //    "dbfactory.php",
                //    "dbresult.php",
                //    "dao.php",
                //    "daofactory.php",
                //    "mysqli.php",
                //    "mysqliresult.php",
                //    "pdo.php",
                //    "pdoresult.php",
                //    "sqlwrapper.php",
                //    "transaction.php",
                //);

                //if (in_array($class_name, $db_files))
                //{
                //    return DIR_CORE."db".DS.$class_name.".php";
                //}

                //$lib_files = array(
                //    "formatshow.php",
                //    "memcachefactory.php",
                //    "logger.php",
                //    "util.php",    
                //);
                //if (in_array($class_name, $lib_files))
                //{
                //    return $filename = DIR_LIBRARY.$class_name.".php";
                //}

			    foreach (self::$autoloadDirs as $dir)
			    {
				    $filename = $dir.$class_name.".php";

				    if (file_exists($filename))
    				{
	    				require_once($filename);
		    			break;
			    	}
			    }
		    }
    	} //end switch
    }

	public static function initBoardConfig()
	{
		//next all, must be after init config,caz need to load board_config
        $mt =  microtime();
        $mt_slice = explode(" ", $mt);
        $time_now = (int)$mt_slice[1];

        SC::set('board_config.microtime_now', str_replace(".", "", $mt_slice[1].$mt_slice[0]));
		SC::set('board_config.time_now', $time_now);//add system time
		//SC::set('board_config.time_now', time());//add system time

		if (SC::get('board_config.debug'))
		{
			ini_set('display_error', true);
			error_reporting(E_ALL);
		}

		//set user ip
		//if (SC::get('board_config.load_user_ip'))
		//{
			$pattern = SC::get('board_config.allow_ip');
			SC::set('board_config.user_ip', Util::getUserIp($pattern));
		//}


        //set if main
		SC::set("board_config.__MAIN__", realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME']) ? true : false);

        //init request id
        //$request_id = NICED_Request::getInstance()->loadParam("request_id");
        //if (!$request_id)
        {
            $request_id = SC::get("board_config.microtime_now").mt_rand(1, 1000000);
        }
        SC::set("board_config.request_id", $request_id);
	}

    private static function initDomainInBoardConfig()
    {
        $host_name_suffix = SC::get("host_name_suffix");
        if(!SC::isEmpty('board_config.local_domain_enable') && isset($_SERVER['SERVER_NAME']) && strpos($_SERVER['SERVER_NAME'], $host_name_suffix) !== false)
        {
            $subdomain = str_replace($host_name_suffix, '', $_SERVER['SERVER_NAME']);

            foreach(self::$secondDomains as $v)
            {
                $key = 'board_config.'.$v.'_server_name_override';

                if(SC::isEmpty($key)) 
                {
                    SC::set($key, $subdomain);
                }
            }
        }

    }

	 public static function exceptionHandler($e)
    {
        if (SC::get("board_config.debug"))
        {
            echo NICED." handle uncatched exception: ".$e->getMessage();
        }
        else
        {
            echo "Server Error From Application";
        }

        NICED_LOG(ERROR, $e->__toString());
    }

    public static function shutdown()
    {
        //init niced request id
        $request_id = SC::get("board_config.request_id");
        NICED_ACCESS_LOG("request_id", $request_id);

        //set to access log
        if (SC::get("board_config.access_log.enable") && function_exists("apache_note"))
        {
            $items = SC::get("board_config.access_log.items");

            if (is_array($items))
            {
                foreach ($items as $k => $v)
                {
                    apache_note($k, $v);
                }
                NICED_LOG(DEBUG, NICED." set access log: ".var_export($items, true));
            }
        }

        //set runtime time to NICED_LOG
        $runtime_time = SC::get("board_config.runtime_time.items");

        if (is_array($runtime_time))
        {
            $str = NULL;
            $items = array();
            $amoniter_param = array(); 
            foreach ($runtime_time as $k => $v)
            {
                if (!isset($v["elapse"]))
                {
                    continue;
                }

                foreach ($v["elapse"] as $key => $value)
                {
                    $str = $key.":".$value;
                    $items[$k] = isset($items[$k]) ? $items[$k].",".$str : $str;
                }
                $last = array_pop($v["stop"]);
                $items[$k] .= ";start:".$v["start"].",stop".$last;
                $amoniter_param[$k] = $last - $v['start'];
            }

            $str = NICED." runtime time: ".Util::buildHttpQuery($items, false, ";") ;
            $log_level = SC::get("board_config.runtime_time.log_level");
            $log_level = $log_level ? $log_level : DEBUG;
            NICED_LOG($log_level, $str);

            // Writes the log to amonitor server.                
           if (class_exists("AmonitorClient"))
           {
            AmonitorClient::push($amoniter_param);   
           }
        }

        //run time memory to log
        $runtime_memory = SC::get("board_config.runtime_memory.items");
        if (is_array($runtime_memory))
        {
            $str = NULL;
            $items = array();
            foreach ($runtime_memory as $k => $v)
            {
                if (!isset($v["elapse"]))
                {
                    continue;
                }

                foreach ($v["elapse"] as $key => $value)
                {
                    $str = $key.":".$value;
                    $items[$k] = isset($items[$k]) ? $items[$k].",".$str : $str;
                }
            }

            $str = NICED." runtime memory: ".Util::buildHttpQuery($items, false, " ") ;
            $log_level = SC::get("board_config.runtime_time.log_level");
            $log_level = $log_level ? $log_level : DEBUG;
            NICED_LOG($log_level, $str);
        }


        //trace info
        $trace_info = SC::get("board_config.trace_info");
        $trace_str  = NICED." Trace: ".implode("\t", $trace_info);
        NICED_LOG(SC::get("board_config.niced_log_level"), $trace_str);
    }

}//end class

spl_autoload_register(array('NICED_Bootstrap', 'autoloadClass'));
